package com.vv.tools.modules.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vv.tools.common.message.CustomerBizException;
import com.vv.tools.common.message.ResultEnum;
import com.vv.tools.common.util.PageUtil;
import com.vv.tools.modules.sys.converter.RoleConvert;
import com.vv.tools.modules.sys.dao.RoleMapper;
import com.vv.tools.modules.sys.entity.Role;
import com.vv.tools.modules.sys.entity.RoleMenu;
import com.vv.tools.modules.sys.model.RoleDTO;
import com.vv.tools.modules.sys.service.RoleMenuService;
import com.vv.tools.modules.sys.service.RoleService;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import static com.vv.tools.common.constant.base.Constant.SUPER_ADMIN;

/**
 * <p>
 * 角色 服务实现类
 * </p>
 *
 * @author vv
 * @since 2025-02-19
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {

    @Autowired
    private RoleMenuService roleMenuService;

    @Override
    public Page<RoleDTO> page(RoleDTO roleDTO) {
        PageUtil<Role> pu = new PageUtil<>(roleDTO);
        Page<RoleDTO> mapper = pu.of(baseMapper).query(Wrappers.lambdaQuery(Role.class)
                .eq(StringUtils.isNotBlank(roleDTO.getName()), Role::getName, roleDTO.getName()))
            .mapper(RoleConvert.INSTANCE::do2dto);
        Set<Long> rids = mapper.getRecords().stream().map(RoleDTO::getId).collect(Collectors.toSet());
        List<RoleMenu> rmList = roleMenuService.list(Wrappers.lambdaQuery(RoleMenu.class).in(RoleMenu::getRoleId, rids));
        if (CollectionUtils.isNotEmpty(rmList)) {
            Map<Long, List<RoleMenu>> rmMap = rmList.stream().collect(Collectors.groupingBy(RoleMenu::getRoleId));
            for (RoleDTO dto : mapper.getRecords()) {
                if (rmMap.containsKey(dto.getId())) {
                    dto.setMenus(rmMap.get(dto.getId()).stream().map(RoleMenu::getMenuId).map(String::valueOf).collect(Collectors.toList()));
                }
            }
        }

        return mapper;
    }

    @Override
    public boolean addRole(RoleDTO roleDTO) {
        // 名字重复校验
        Role dbRole = baseMapper.selectOne(Wrappers.lambdaQuery(Role.class).eq(Role::getName, roleDTO.getName()));
        if (null != dbRole) {
            throw new CustomerBizException(ResultEnum.ROLES_NAME_REPEAT);
        }

        Role role = RoleConvert.INSTANCE.dto2do(roleDTO);
        role.setId(null);
        return this.save(role) && isSaveMenu(roleDTO.getMenus(), role.getId());
    }

    @Override
    public boolean updateRole(RoleDTO roleDTO) {
        // 用户是否存在
        Role checkRole = baseMapper.selectById(roleDTO.getId());
        if (null == checkRole) {
            throw new CustomerBizException(ResultEnum.ROLES_ROLE_NOT_EXIST);
        }

        Role role = RoleConvert.INSTANCE.dto2do(roleDTO);
        // 角色名字不能修改
        role.setName(null);
        return this.updateById(role) && isSaveMenu(roleDTO.getMenus(), role.getId());
    }

    @Override
    public boolean deleteRole(Long id) {
        if (SUPER_ADMIN.equals(id)) {
            throw new CustomerBizException(ResultEnum.SUPER_ADMIN_ROLE_NOT_DELETE);
        }

        return this.removeById(id);
    }


    private boolean isSaveMenu(List<String> menus, Long roleId) {
        // 新增角色
        boolean saveMenus = false;
        if (CollectionUtils.isNotEmpty(menus)) {
            // 先判断角色是否一致
            LambdaQueryWrapper<RoleMenu> eq = Wrappers.lambdaQuery(RoleMenu.class).eq(RoleMenu::getRoleId, roleId);
            List<RoleMenu> urList = roleMenuService.list(eq);
            Set<String> ms = urList.stream().map(RoleMenu::getMenuId).map(String::valueOf).collect(Collectors.toSet());
            boolean equalCollection = CollectionUtils.isEqualCollection(ms, menus);
            if (equalCollection) {
                return true;
            }
            // 不一致就先批量删除，在批量保存
            roleMenuService.remove(eq);
            List<RoleMenu> list = new ArrayList<>();
            for (String mid : menus) {
                RoleMenu rm = new RoleMenu();
                rm.setRoleId(roleId);
                rm.setMenuId(Long.valueOf(mid));
                list.add(rm);
            }
            saveMenus = roleMenuService.saveBatch(list);
        }
        return saveMenus;
    }

}
